<?php

abstract class Common_Task extends ClassStructure_Mixin_Delegator {

    
    public function __construct($arr_options = array()) {
        parent::__construct();
        $this->__addMixin('property');
        
        $this->property__setProperties($arr_options);
    }
    
    public function getName() {
        return get_class($this);
    }
    
    final public function execute($arr_options = array()) {
        
        $bln_success = false;
        
        $str_name = $this->getName();
        
        $this->log("Starting task [$str_name]");
        
        $flt_time_start = microtime(true);
        
        $arr_options = (array) $arr_options;
        
        if(!empty($arr_options)) {
            $int_options = count($arr_options);
            $this->log("Merging [$int_options] specific options");
            $arr_options = array_merge($this->property__getProperties(), $arr_options);
        } else {
            $arr_options = $this->property__getProperties();
        }
        
        try {
            
            $this->log("Trying to execute services");
            $bln_success = $this->tryTask($arr_options);
            
        } catch(Exception $obj_exception) {
            
            $this->log("Catching internal exception");
            $this->catchException($obj_exception, $arr_options);
            
        }
        
        $this->log("Executing final services");
        $this->finallyExecute($arr_options);
        
        $flt_time_end = microtime(true);
        
        $flt_elapsed_time = $flt_time_end - $flt_time_start;
        $str_elapsed_time = number_format($flt_elapsed_time, 5);
        
        $str_success = $bln_success ? 'successfully' : 'unsuccessfully';
        $enm_priority = $bln_success ? Zend_Log::INFO : Zend_Log::NOTICE;
        
        $this->log("Task ended $str_success [$str_elapsed_time secs]", $enm_priority);
        
        return $bln_success;
    }
    
    public function setLogger(Zend_Log $obj_logger) {
        $this->__addMixin($obj_logger, 'log');
    }
    
    public function getLogger() {
        return $this->__getMixin('log');
    }

    public function hasLogger() {
        return $this->__hasMixin('log');
    }
    
    protected function log($str_message, $enm_priority = Zend_Log::INFO) {
        if($this->hasLogger()) {
            $this->log__log($str_message, $enm_priority);
        }
    }
    
    final protected function tryTask($arr_options) {
        
        $bln_success = false;
        
        $this->log("Initialising task services");
        $this->initialiseTask($arr_options);
        
        $this->log("Validating task input");
        $bln_valid = $this->validateInput($arr_options);
        
        if($bln_valid) {
            
            $this->log("Initialising task services");
            $this->initialiseTask($arr_options);
            
            $this->log("Executing task services");
            $bln_success = (boolean) $this->executeTask($arr_options);
            
        } else {
            
            $this->log("Task input did not validate successfully", Zend_Log::ERR);
            
        }
        
        return $bln_success;
        
    }
    
    protected function catchException(Exception $obj_exception, $arr_options) {
        
        $str_exception_type = get_class($obj_exception);
        $str_message = $obj_exception->getMessage();
        
        $this->log("Exception [$str_exception_type] caught with following message: $str_message");
        
        if(isset($arr_options['rethrow_exceptions']) && ($arr_options['rethrow_exceptions'] === true)) {
            throw $obj_exception;
        }
        
    }
    
    protected function finallyExecute($arr_options) {
    }
    
    protected function validateInput($arr_options) {
        return true;
    }

    protected function initialiseTask($arr_options) {
    }

    abstract protected function executeTask($arr_options);
    
    public function getOutput() {
        return null;
    }
    
}
